﻿//===============================================================================
//	GameServer.cpp
//	游戏服务器
//===============================================================================

#ifdef _MSC_VER
#ifdef USE_VLD_CHECK_LEAK
#include "vld.h"
#endif
#endif

#include "GameServer.h"

#include "../../3rd/libjson/json.h"
#include "../../3rd/libjson/LZW.h"

#include "ManagerHelper.h"

#include "LuaScriptManager.h"
#include "../share/MessageDef.h"
#include "playerinfo_mgr.h"
#include "../share/proxyclient_service.h"
#include "../share/GameHostManager.h"
#include "../share/client_msg.h"
#include "MapSlot.h"
#include "game_logic.h"
#include "sceneobj_manager.h"
#include "scene_logic.h"
#include "../share/tplmgr.h"
#include "union_module.h"
#include "union.h"
#include "../share/time_module.h"
#include "../share/base.h"
#include "activity_module.h"
#include "PlayerLevelUpCacheData.h"
#include "../share/dirtyword.h"
#include "team_mgr.h"
#include "mail_module.h"
#include "chat_module.h"
#include "MonsterCacheData.h"


#ifdef _MSC_VER
char * g_dump_exe_name = "GameServer";
#endif

GameServer::GameServer()
{
	client_gate_fd = 0;
}

GameServer::~GameServer()
{

}

int32_t GameServer::Initialize()
{
	update_time_ = CUR_SEC;
	CGameObjManager::GetInstance().Initialize();
	manager_helper::InitializeAllManager(8, 1);

	//manager_helper::RegistRankListData();

	MapSlot::GetInstance().Init();

	uint16_t _listen_port = GameHostManager::GetInstance().GetGameHostListenPort();
	if (0 == _listen_port)
	{
		LOG_ERROR("default","ERROR >> Read game server listen port fail");
		return -1;
	}

	game_net_.Initialize(1024 * 100, 1024 * 100);
	game_net_.Startup(_listen_port);
	
	CProxyClientService::GetInstance().InitializeServer(GetServiceType(), GetServiceID(), this);
	CProxyClientService::GetInstance().Initialize(1024 * 100, 1024* 100);

	if (CPlayerInfoMgr::GetInstance().Initialize() == false)
	{
		LOG_ERROR("default","ERROR >> READ PLAYER INFO ERR");
		return -1;
	}

	MapSlot::GetInstance().ChangeGameSrvOnlineAmountToRedisDB();
	CGameLogic::GetInstance().Initialize();
	CTPLManager::GetInstance().LoadTPL();
	CUnionModule::GetInstance().Initialize();
	CSceneLogic::GetInstance().Initialize();
	CActivityModule::GetInstance().Init();
	CTeamMgr::GetInstance().Initialize();
	MonsterCacheData::GetInstance().Initialization();
	PlayerLevelUpCacheData::GetInstance().Initialization();
	CDirtyWord::GetInstance().OI_Dirty_start();
	CMailModule::GetInstance().Initialize();
	CChatModule::GetInstance().Initialize();
	return 0;
}

void GameServer::TickUpdate() 
{
	CGuildManager::GetInstance().TickUpdate();
	CActivityModule::GetInstance().TickUpdate();
	MapSlot::GetInstance().TickUpdate();
	//CSceneManager::GetInstance().TickUpdate();
	CSceneLogic::GetInstance().TickUpdate();
	time_t cur_sec = CUR_SEC;
	if (cur_sec <= update_time_)
	{
		return;
	}
	tm* update_tm = localtime(&update_time_);
	if (NULL == update_tm)
	{
		return;
	}
	time_t day_time = ::common::RebuildTime(update_tm, 50000);
	time_t day_zero_time = day_time - 5 * 60 * 60;
	int32_t week_day = update_tm->tm_wday;
	if (week_day == 0)
	{
		week_day = 7;
	}
	int32_t week_time = day_time - (week_day - 1) * 24 * 60 * 60;
	if (update_time_ > day_time)
	{
		day_time += 24 * 60 * 60;
	}
	if (update_time_ > day_zero_time)
	{
		day_zero_time += 24 * 60 * 60;
	}
	if (update_time_ > week_time)
	{
		week_time += 7 * 24 * 60 * 60;
	}
	if (cur_sec >= day_time &&
		update_time_ < day_time)
	{
		OnNewDay();
	}
	if (cur_sec >= day_zero_time &&
		update_time_ < day_zero_time)
	{
		OnNewZeroDay();
	}
	if (cur_sec >= week_time &&
		update_time_ < week_time)
	{
		OnNewWeek();
	}
	update_time_ = cur_sec;

}

int32_t GameServer::Finalize()
{
	CGameObjManager::GetInstance().Finalize();
	CGameObjManager::ReleaseInstance();
	manager_helper::DestoryAllManager();
	CPlayerInfoMgr::GetInstance().Finalize();
	MapSlot::ReleaseInstance();
	CGameLogic::ReleaseInstance();
	CTPLManager::ReleaseInstance();
	CUnionModule::GetInstance().Finalize();
	CSceneLogic::ReleaseInstance();
	CActivityModule::GetInstance().Finalize();
	CTeamMgr::GetInstance().Finalize();
	CMailModule::GetInstance().Finalize();
	return 0;
}

int32_t GameServer::client_msg_dispatch(std::string& msg, unsigned long uid, uint32_t msgId)
{
	Json::Value m_jv;
	m_jv["msg"] = msg;
	m_jv["_gate_fd"] = (int32_t)uid;
	std::string send_str = JsonWriter(m_jv);
	Player * player = CSceneLogic::GetInstance().GetPlayerBySocket(uid);
	if (player == nullptr) {
		LOG_ERROR("default", "game - gate msg error player is null or cant find socket fd");
		return 0;
	}

	const char* msg_body = send_str.c_str();
	CGameChannel* game_channel = game_net_.GetChannel(client_gate_fd);
	if (NULL == game_channel) {
		return -1;
	}
	::common::CNetMsgTransfer::out_tcp_for_client(*game_channel, client_gate_fd, msgId, msg_body, msg.size());
	return ::common::SUCCEED;
}

void GameServer::client_close_socket(uint32_t uid)
{
	LOG_INFO("default"," close client uid:%u", uid);
	game_net_.CloseChannel(uid);
}

bool GameServer::is_connnected(uint32_t uid)
{
	return false;
}

bool GameServer::send_by_uid(uint32_t uid, std::string& msg, uint32_t msgId)
{
	Json::Value m_jv;
	m_jv["msg"] = msg;
	m_jv["_gate_fd"] = (int32_t)uid;
	std::string send_str = JsonWriter(m_jv);
	CGameChannel* game_channel = game_net_.GetChannel(client_gate_fd);
	if (NULL == game_channel) {
		return false;
	}
	::common::CNetMsgTransfer::out_tcp_for_client(*game_channel,client_gate_fd,msgId, send_str.c_str(), send_str.length());
	return true;
}

void GameServer::broadcast_msg_to_client(std::string& msg, uint32_t msgId)
{
	const TObjIDMap& socket_online = CSceneLogic::GetInstance().GetOnlineSocket();
	TObjIDMap::const_iterator iter = socket_online.begin();
	while (iter != socket_online.end())
	{
		send_by_uid(iter->first, msg, msgId);
	}
}

void GameServer::del_client_socket(uint32_t fd)
{
	LOG_INFO("default"," del client uid:%u", fd);
	// 这里考虑添加事件触发，而不是直接调用，会有多线程的问题
	//CSceneLogic::GetInstance().OnPlayerDisconnect(fd);
}

int32_t GameServer::ServerStart()
{
	CProxyClientService::GetInstance().CheckConnect();
	CProxyClientService::GetInstance().EnableReconnect(2000);
	// game 启动通知login
	Json::Value notify;
	notify["msgid"] = g2l_gameserver_start_notify;
	std::string str = JsonWriter(notify);
	send_2_login(g2l_gameserver_start_notify, str);

	CGameLogic::GetInstance().PlayerNumReportStart();

	// game 启动 请求平台确认map更换
	notify.clear();
	notify["msgid"] = g_plat_change_map_req;
	notify["ret"] = ::common::SUCCEED;
	str.clear();
	str = JsonWriter(notify);
	send_2_platform(g_plat_change_map_req, str);

	return 0;
}

void GameServer::OnNewDay()
{
	CGuildManager::GetInstance().OnNewDay();
	LOG_DEBUG("default","on new day come!");
}

void GameServer::OnNewZeroDay()
{
	CSceneLogic::GetInstance ().CheckSendEmail4SurpriseRecharge();
	LOG_DEBUG("default","on new zero day come!");
}

void GameServer::OnNewWeek()
{
	CGuildManager::GetInstance().OnNewWeek();
	LOG_DEBUG("default","on new week come!");
}

int32_t GameServer::ServiceMainLoop()
{
	EServiceStatus service_statuss = GetServiceStatus();
	if (service_statuss == SERVICE_WAITTING_EXIT)
	{
		// 服务器等待退出，开始保存数据
		SceneServiceWattingExit();
	}

	//CSceneLogic::GetInstance().PlayerDestroyDoing();

	return ::common::SUCCEED;
}

void GameServer::SceneServiceWattingExit()
{
	if (CUR_SEC % 5 == 0)
	{
		CSceneLogic::ServiceExitting();

		// 公会数据保存
		CGuildManager::GetInstance().SaveGuild();
		int32_t guild_left = CGuildManager::GetInstance().GuildSaveLeft();

		int32_t playerinfo_left = CPlayerInfoMgr::GetInstance().SaveRoles(10);

		int32_t player_count = CGameObjManager::GetInstance().GetMemberSize(OBJTYPE_PLAYER);
		if (player_count != 0 && playerinfo_left != 0 && guild_left != 0)
		{
			LOG_INFO("default","game service waitting exit, player left %d, playerinfo_left %d, guild_left %d", player_count, playerinfo_left, guild_left);
		}
		else
		{
			LOG_INFO("default","game service waitting exit, all player exit");

			Exit(::common::ESERVICE_SIGNAL_USR1_ASKED);
		}
	}
}

void GameServer::OnUserSignal1()
{
	SetServiceStatus(SERVICE_WAITTING_EXIT);
}

int32_t GameServer::AddClientMsg(uint32_t socketId, uint32_t msgId, std::string &msg)
{
	CJsonMessageBase bmsg;
	bool ret = bmsg.ParseAcceptJson(msg);
	const Json::Value tmp_jv = bmsg.GetJsonValue();

	int32_t gate_fd = tmp_jv["_gate_fd"].asInt();
	int32_t msg_id = tmp_jv["msgid"].asInt();

	// 注册gate
	if (msg_id == register_gate_to_game)
	{
		client_gate_fd = socketId;
		return 0;
	}


	CClientSocketMsg client_msg;
	client_msg.SetMsg(msg, gate_fd, msg_id);
	AddClientMsgPtr(client_msg);
	return 0;
}

void GameServer::ProcessClientMsg(CClientSocketMsg& val)
{
	LOG_DEBUG("default"," process socket msg %d processed Begin =====", val.m_protocol_number);

	CJsonMessageBase msg;
	bool ret = msg.ParseAcceptJson(val.msg_);
	if (ret == false)
	{
		LOG_ERROR("default","msg parse err!  msgid[%d][%s]", val.m_protocol_number, val.msg_.c_str());
		return;
	}
	msg.set_from_socket_id(val.fd_);
	// 第一个登陆game请求
	if (val.m_protocol_number == c2g_player_enter_game_req)
	{
		CGameLogic::GetInstance().OnMsgC2GEnterGameRequest(val.fd_, msg);
		return;
	}

	Player* player = CSceneLogic::GetInstance().GetPlayerBySocket(val.fd_);
	if (player == NULL)
	{
		if (val.fd_ > 0 && ret) {
			CGameLogic::GetInstance().OnMsgC2GEnterGameRequest(val.fd_, msg);
			player = CSceneLogic::GetInstance().GetPlayerBySocket(val.fd_);
		}
		LOG_INFO("default","player is not online when process msg[%d]", val.m_protocol_number);

		if (player == NULL) {
			return;
		}
	}

	GamePlayerMsgProcess process = GameServer::GetInstance().GetPlayerMsgFactory().GetMsgProcess(val.m_protocol_number);
	if (process == NULL)
	{
		LOG_ERROR("default","process is null! msgid[%u]", val.m_protocol_number);
		return;
	}
	LOG_DEBUG("default","client[%d] msg:[%d][%s]", val.fd_, val.m_protocol_number, val.msg_.c_str());
	process(*player, msg);

	LOG_DEBUG("default"," process socket msg %d processed OK =====", val.m_protocol_number);
}

int32_t GameServer::SendToGate(std::string& msg, uint32_t msgId)
{
	//return 0;
	//server_net.client_msg_dispatch(msg, client_gate_fd, msgId);
	return 0;
}


void CGameChannel::OnMsgEvent()
{
	while (true)
	{

		uint32_t msg_id = 0;

		std::string content;

		bool ret_trans = ::common::CNetMsgTransfer::in_tcp_for_client(*this, content, msg_id);

		if (ret_trans == false) {
			return;
		}
		CJsonMessageBase bmsg;
		bool ret = bmsg.ParseAcceptJson(content);
		const Json::Value tmp_jv = bmsg.GetJsonValue();

		int32_t gate_fd = tmp_jv["_gate_fd"].asInt();
		//int32_t msg_id = tmp_jv["msgid"].asInt();
		uint32_t area_id = tmp_jv["_area_id"].asUInt();

		// 注册gate
		if (msg_id == register_gate_to_game)
		{
			GameServer::GetInstance().SetGateFd(fd());
			return;
		}


		CClientSocketMsg client_msg;
		client_msg.SetMsg(content, gate_fd, msg_id);
		GameServer::GetInstance().ProcessClientMsg(client_msg);


	}
}

void CGameChannel::OnConnect()
{
	LOG_ERROR("default", "on connect");
}

void CGameChannel::OnDisconnect()
{
	LOG_ERROR("default", "on disconnect");
	GameServer::GetInstance().del_client_socket(fd());
}


int main(int argc, char* argv[])
{
#ifdef _MSC_VER
	SetCtrlCHandle(true);
#endif
	int retcode = GameServer::GetInstance().ServiceMain(argc, argv);
	GameServer::ReleaseInstance();
#ifdef _MSC_VER
	SetCtrlCHandle(false);
#endif
	return retcode;
}